package com.foreveross.crawl.common.application;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.dayatang.domain.InstanceFactory;
import org.dayatang.querychannel.QueryChannelService;
import org.openkoala.exception.extend.ApplicationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.foreveross.crawl.common.core.ChannelInfoEntity;
import com.foreveross.crawl.common.core.ProxyChannelRelateEntity;
import com.foreveross.crawl.common.core.ProxyIpEntity;
import com.foreveross.crawl.vo.ProxyChannelRelateVO;

@Service
@Transactional
public class ProxyChannelRelateApplicationImpl implements
		IProxyChannelRelateApplication {

	private Logger logger = Logger.getLogger(ProxyChannelRelateApplicationImpl.class);

	private QueryChannelService queryChannelService;
	
	public QueryChannelService getQueryChannelService() {
		if (queryChannelService == null) {
			queryChannelService = InstanceFactory.getInstance(QueryChannelService.class, "queryChannel_ss");
		}
		return queryChannelService;
	}
	
	@Override
	public void saveProxyIp(ProxyChannelRelateVO vo) throws Exception {
		ProxyIpEntity domain = ProxyChannelRelateVO.voToProxyIp(vo);
		if(ProxyIpEntity.isProxyIpExisted(vo.getIp())){
			throw new ApplicationException("代理IP已存在");
		}
		domain.save();
	}

	@Override
	public void saveChannelInfo(ProxyChannelRelateVO vo) throws Exception {
		ChannelInfoEntity domain = ProxyChannelRelateVO.voToChannelInfo(vo);
		if (ChannelInfoEntity.isChannelExisted(vo.getChannelId())) {
			throw new ApplicationException("渠道ID已存在");
		}
		domain.save();
	}
	
	@Override
	public void saveProxyChannelRelate(ProxyChannelRelateVO vo) throws Exception{
		ProxyChannelRelateEntity domain = ProxyChannelRelateVO.voToProxyChannelRelate(vo);
		domain.save();
	}
	
	@Override
	public void saveOrUpdateProxyIp(Long channelId, String channelName, String ip) throws Exception{
		this.saveOrUpdateProxyIp(channelId, channelName, ip, true);
	}
	
	@Override
	public void saveOrUpdateProxyIp(Long channelId, String channelName, String ip, boolean isSuccess) throws Exception{
		ProxyChannelRelateVO vo = new ProxyChannelRelateVO(channelId, channelName, ip);
		ProxyIpEntity proxyDomain = ProxyChannelRelateVO.voToProxyIp(vo);
		ChannelInfoEntity channelDomain = ProxyChannelRelateVO.voToChannelInfo(vo);
		ProxyChannelRelateEntity pcDomain = ProxyChannelRelateVO.voToProxyChannelRelate(vo);
		//1. 获取代理ip信息
		if(!ProxyIpEntity.isProxyIpExisted(ip)){//不存在时插入
			proxyDomain.setCreateDate(new Date());
			proxyDomain.save();
		} else {
			proxyDomain = ProxyIpEntity.findProxyIpByIp(ip);
		}
		//2. 获取渠道信息
		if(!ChannelInfoEntity.isChannelExisted(channelId)){//不存在时，插入记录
			channelDomain.setCreateDate(new Date());
			channelDomain.save();
		} else {
			channelDomain = ChannelInfoEntity.findChannelInfoByChannelId(channelId);
		}
		//3. 渠道及代理ip关联关系是否存在
		if(!ProxyChannelRelateEntity.isProxyChannelRelateExisted(channelDomain, proxyDomain)){//不存在
			pcDomain.setChannelInfo(channelDomain);
			pcDomain.setProxyIp(proxyDomain);
			pcDomain.setCreateDate(new Date());
			if(isSuccess){
				pcDomain.setSuccessNumber(1L);
				pcDomain.setFailNumber(0L);
			} else {
				pcDomain.setFailNumber(1L);
				pcDomain.setSuccessNumber(0L);
				pcDomain.setDisableDate(new Date());
			}
			pcDomain.save();
		} else {
			if(isSuccess){
				updateProxyIpOfSuccessNumber(channelId, ip);
			} else {
				updateProxyIpOfFailNumber(channelId, ip);
			}
		}
	}

	@Override
	public void deleteAllProxyIp() {

		ProxyIpEntity.deleteAll();
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void deleteAllChannelInfo() {

		ChannelInfoEntity.deleteAll();
	}

	@Override
	public void deleteAllProxyChannelRelate() {

		ProxyChannelRelateEntity.deleteAll();
	}
	
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void clearAll(){
		
		ProxyChannelRelateEntity.deleteAll();//因为存在外键，必须首先删除该对象
		ChannelInfoEntity.deleteAll();
		ProxyIpEntity.deleteAll();
	}

	@Override
	public void updateProxyIpOfSuccessNumber(Long channelId, String proxyIp) {

		ChannelInfoEntity channelEntity = ChannelInfoEntity.findChannelInfoByChannelId(channelId);
		ProxyIpEntity proxyIpEntity = ProxyIpEntity.findProxyIpByIp(proxyIp);
		ProxyChannelRelateEntity.updateProxyIpOfSuccessNumber(channelEntity, proxyIpEntity);
	}

	@Override
	public void updateProxyIpOfFailNumber(Long channelId, String proxyIp) {

		ChannelInfoEntity channelEntity = ChannelInfoEntity.findChannelInfoByChannelId(channelId);
		ProxyIpEntity proxyIpEntity = ProxyIpEntity.findProxyIpByIp(proxyIp);
		ProxyChannelRelateEntity.updateProxyIpOfFailNumber(channelEntity, proxyIpEntity);
	}

	@Override
	public ProxyChannelRelateVO getProxyIpByIp(String ip) throws Exception{
		ProxyIpEntity domain = ProxyIpEntity.findProxyIpByIp(ip);
		return ProxyChannelRelateVO.domainToVo(domain);
	}
	
	@Override
	public ProxyChannelRelateVO getChannelInfoByChannelId(Long channelId) throws Exception{
		ChannelInfoEntity domain = ChannelInfoEntity.findChannelInfoByChannelId(channelId);
		return ProxyChannelRelateVO.domainToVo(domain);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<ProxyChannelRelateVO> getStatisticsByChannel(int pageCurrent, int pageSize) {
		String jpql = "select NEW com.foreveross.crawl.vo.ProxyChannelRelateVO(t.proxyIp.id, t.channelInfo.channelId, t.channelInfo.channelName, t.proxyIp.ip, sum(t.successNumber), sum(t.failNumber), t.createDate, t.disableDate) from ProxyChannelRelateEntity t group by t.proxyIp, t.channelInfo, t.createDate, t.disableDate order by t.createDate desc";
		List<ProxyChannelRelateVO> list = null;
		try {
			list = this.getQueryChannelService().createJpqlQuery(jpql).list();
		} catch (Exception e) {
			logger.error(e);
		}
		return dealStatisticsByChannelResult(list);
	}

	private List<ProxyChannelRelateVO> dealStatisticsByChannelResult(List<ProxyChannelRelateVO> list) {
		List<ProxyChannelRelateVO> retList = new ArrayList<ProxyChannelRelateVO>();
		List<Long> channelIdListByAdded = new ArrayList<Long>();
		for(int i = 0; i < list.size(); i++){
			ProxyChannelRelateVO vo1 = list.get(i);
			if(channelIdListByAdded != null && channelIdListByAdded.size() != 0 && channelIdListByAdded.contains(vo1.getId())){
				continue;
			}
			for(int j = i + 1; j < list.size(); j++){
				ProxyChannelRelateVO vo2 = list.get(j);
				if(vo1.getId() == vo2.getId() || vo1.getId().equals(vo2.getId())){
					vo1.setSuccessNumber((vo1.getSuccessNumber() != null ? vo1.getSuccessNumber() : 0) + (vo2.getSuccessNumber() != null ? vo2.getSuccessNumber() : 0));
					vo1.setFailNumber((vo1.getFailNumber() != null ? vo1.getFailNumber() : 0) + (vo2.getFailNumber() != null ? vo2.getFailNumber() : 0));
				}
			}
			retList.add(vo1);
			channelIdListByAdded.add(vo1.getId());
		}
				
		return retList;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<ProxyChannelRelateVO> getStatisticsByProxyIp(String proxyIp, int pageCurrent, int pageSize) {
		ProxyIpEntity proxyIpEntity = ProxyIpEntity.findProxyIpByIp(proxyIp);
		String jpql = "select NEW com.foreveross.crawl.vo.ProxyChannelRelateVO(t.channelInfo.channelId, t.channelInfo.channelName, t.proxyIp.ip, sum(t.successNumber), sum(t.failNumber)) from ProxyChannelRelateEntity t where t.proxyIp=:ip group by t.channelInfo";
		List<ProxyChannelRelateVO> list = this.getQueryChannelService().createJpqlQuery(jpql).addParameter("ip", proxyIpEntity).list();
		return list;
	}
	
}
